#include "iotgo_communicate_with_long_server.h"
#include "iotgo_data_pool.h"
#include "iotgo_memory_hooks.h"
#include "iotgo_mySocketClient_interface.h"
#include "iotgo_heart_beat_task.h"
#include "iotgo_debug.h"

#define debugPrint longServerDebugPrint

#ifndef FAIL
#define FAIL (-1)
#endif

/* macro: data type */
#define LSERVER_DATA_TYPE_UPDATE         1
#define LSERVER_DATA_TYPE_UPGRADE        2
#define LSERVER_DATA_TYPE_QUERY_DATE     3
#define LSERVER_DATA_TYPE_QUERY_PARAMS   4

/* macro: data length*/
#define LSERVER_IP_LENGTH 16

/* macro: websocket update massage flag*/
#define UPDATE_TO_WEBSOCKET_DONE 1

/* used in communicateWithLongServer*/
static volatile int communicate_state = LSERVER_IS_NOT_STARTED;
static MySocketClient *p_socket = NULL;
static uint8_t user_apikey[37] = "wrong apikey!";

static int8_t updateToWebSocket(void);
static int8_t registerToServer(void);
static int32_t handleWebSocketData(void);
static int produceWebsocktData(char *data, char *buf);
static int sendRegisterMessage(void);

int communicateWithLongServer(void)
{
    int32_t ret = -1;
    uint8_t  server_ip[LSERVER_IP_LENGTH] = {0};
    uint32_t server_port = 0;

    switch(communicate_state)
    {
    case LSERVER_IS_NOT_STARTED:
        /*init*/
        /*1. get lserver info*/
        ret = getLServerInfo(server_ip,&server_port);
        /*2. get the socket */
        if(ret == 0)
        {
            p_socket = setupSocketClient(server_ip,server_port);
        }

        /*3. get the data pool done*/
        ret = createIotgoDataPool();
        /*4. check */
        if(ret != FAIL && p_socket)
        {
            communicate_state = LSERVER_HAS_INITED;
            ret = LSERVER_ERROR_NOT_FINISHED;
        }
        else
        {
            cleanWithLongServer();
            ret = LSERVER_ERROR_INIT;
        }
        break;
    case LSERVER_HAS_INITED:
        /*try to get the sokcet ready*/
        ret = connectToServer(p_socket);
        if(ret == MYSOCKETCLIENT_SUCCESS)
        {
            communicate_state = LSERVER_SOCKET_IS_READY;
            ret = LSERVER_ERROR_NOT_FINISHED;
        }
        else if(ret == MYSOCKETCLIENT_FAIL)
        {
            ret = LSERVER_ERROR_CONNECT;
        }
        else
        {
            ret = LSERVER_ERROR_NOT_FINISHED;
        }
        break;
    case LSERVER_SOCKET_IS_READY:
        /*try to update to websocket*/
        ret = updateToWebSocket();
        if(ret == UPDATE_TO_WEBSOCKET_DONE)
        {
            debugPrint("[%s] updateToWebSocket done\n",__FUNCTION__);
            communicate_state = LSERVER_WEBSOCKET_IS_READY;
        }
        ret = LSERVER_ERROR_NOT_FINISHED;
        break;
    case LSERVER_WEBSOCKET_IS_READY:
        /*try to register to long server*/
        sendRegisterMessage();
    case LSERVER_REGISTER_IS_READY:
        ret = handleWebSocketData();
        if(ret <= 0)
        {
            debugPrint("[%s] handleWebsocketData() ret is %d\n",__FUNCTION__,ret);
            ret = LSERVER_ERROR_COMMUNICATE;
        }
        else
        {
            ret = LSERVER_ERROR_NONE;
        }
        break;
    default:
        break;
    }
    return ret;
}

int cleanWithLongServer(void)
{
    debugPrint("[%s]cleanWithLongServer start\n",__FUNCTION__);
    print_memory_heap();
    cleanSocketClient(&p_socket);
    debugPrint("[%s]testpoint1\n",__FUNCTION__);
    releaseIotgoDataPool();
    debugPrint("[%s]testpoint2\n",__FUNCTION__);
    communicate_state = LSERVER_IS_NOT_STARTED;
    stopHeartBeat();
    debugPrint("[%s]cleanWithLongServer end\n",__FUNCTION__);
    print_memory_heap();
    return LSERVER_ERROR_NONE;
}

int getStateWithLongServer(void)
{
    return communicate_state;
} 

//extern int writeToServer(uint8_t *buf);
int writeErrorNumToServer(uint32_t num,uint8_t *sequence)
{
    uint8_t deviceID[STRING_DEVICE_ID_LEN] = "wrong ID!";
    uint8_t apikey[STRING_API_KEY_LEN] = "wrong apikey!";

    int32_t ret = -1;
    int32_t len = -1;

    cJSON *cjson_Websocket_send = NULL;
    char *cjson_send = NULL;

    uint8_t send_buf[500] = {0};
    
    cJSON_Hooks memoryHook;
    memoryHook.malloc_fn = pMalloc;
    memoryHook.free_fn = pFree;
    cJSON_InitHooks(&memoryHook);
    
    /*step0 : make sure stream is ok*/
    if(communicate_state != LSERVER_REGISTER_IS_READY)
    {
        return -1;
    }
    /*step1 : get device info*/
    ret = getDeviceInfo(deviceID,apikey);
    /* return message to server*/
    if( (cjson_Websocket_send = cJSON_CreateObject()) != NULL)
    {
        cJSON_AddItemToObject(cjson_Websocket_send ,"error" ,cJSON_CreateNumber(num));
        cJSON_AddItemToObject(cjson_Websocket_send ,"apikey" ,cJSON_CreateString(user_apikey));
        cJSON_AddItemToObject(cjson_Websocket_send ,"deviceid" ,cJSON_CreateString(deviceID));
        cJSON_AddItemToObject(cjson_Websocket_send ,"sequence" ,cJSON_CreateString(sequence));
    }
    cjson_send = cJSON_PrintUnformatted(cjson_Websocket_send);
    len = produceWebsocktData(cjson_send, send_buf);
    ret = writeToServer(p_socket,send_buf,len);
    pFree(cjson_send);
    cJSON_Delete(cjson_Websocket_send);
    return 0;
}

int writeUpdateToServer(uint8_t *params)
{
    uint8_t deviceID[STRING_DEVICE_ID_LEN] = "wrong ID!";
    uint8_t apikey[STRING_API_KEY_LEN] = "wrong apikey!";
    uint8_t rom_version[STRING_ROM_VERSION_LEN] = "wrong FW";

    cJSON *cjson_userAPIKey = NULL;
    cJSON *cjson_Websocket_send = NULL;
    cJSON *cjson_params = NULL;
    char *cjson_send = NULL;

    int32_t ret,len;
    uint8_t send_buf[500] = {0};
    
    cJSON_Hooks memoryHook;

    memoryHook.malloc_fn = pMalloc;
    memoryHook.free_fn = pFree;
    cJSON_InitHooks(&memoryHook);
    /*step0 : make sure stream is ok*/
    if(communicate_state != LSERVER_REGISTER_IS_READY)
    {
        return -1;
    }
    /*step1 : get device info*/
    ret = getDeviceInfo(deviceID,apikey);
    ret = getFWVersion(rom_version);

    /*step2 : change params string to cjson */
    if( (cjson_params = cJSON_Parse(params)) != NULL)
    {
        /*step3 : make update data*/
        if( (cjson_Websocket_send = cJSON_CreateObject()) != NULL)
        {
            cJSON_AddItemToObject(cjson_Websocket_send ,"action" ,cJSON_CreateString("update"));
            cJSON_AddItemToObject(cjson_Websocket_send ,"userAgent" ,cJSON_CreateString("device"));
            cJSON_AddItemToObject(cjson_Websocket_send ,"apikey" ,cJSON_CreateString(user_apikey));
            cJSON_AddItemToObject(cjson_Websocket_send ,"deviceid" ,cJSON_CreateString(deviceID));
            cJSON_AddItemToObject(cjson_Websocket_send, "params", cjson_params);
            cJSON_AddItemToObject(cjson_params, "fwVersion", cJSON_CreateString(rom_version));
        }
        /*step4 : update*/
        cjson_send = cJSON_PrintUnformatted(cjson_Websocket_send);
        debugPrint("[%s]update cjson is :\n%s\n",__FUNCTION__,cjson_send);
        len = produceWebsocktData(cjson_send, send_buf);
        ret = writeToServer(p_socket,send_buf,len);
        pFree(cjson_send);
        cJSON_Delete(cjson_Websocket_send);
    }

    return 0;
}

int writeQueryToServer(uint8_t *params)
{
    uint8_t deviceID[STRING_DEVICE_ID_LEN] = "wrong ID!";
    uint8_t apikey[STRING_API_KEY_LEN] = "wrong apikey!";
    uint8_t rom_version[STRING_ROM_VERSION_LEN] = "wrong FW";

    cJSON *cjson_userAPIKey = NULL;
    cJSON *cjson_Websocket_send = NULL;
    cJSON *cjson_params = NULL;
    char *cjson_send = NULL;

    int32_t ret,len;
    uint8_t send_buf[500] = {0};
    
    cJSON_Hooks memoryHook;

    memoryHook.malloc_fn = pMalloc;
    memoryHook.free_fn = pFree;
    cJSON_InitHooks(&memoryHook);
    /*step0 : make sure stream is ok*/
    if(communicate_state != LSERVER_REGISTER_IS_READY)
    {
        return -1;
    }

    /*step1 : get device info*/
    ret = getDeviceInfo(deviceID,apikey);
    ret = getFWVersion(rom_version);

    /*step2 : change params string to cjson */
    if( (cjson_params = cJSON_Parse(params)) != NULL)
    {
        /*step3 : make update data*/
        if( (cjson_Websocket_send = cJSON_CreateObject()) != NULL)
        {
            cJSON_AddItemToObject(cjson_Websocket_send ,"action" ,cJSON_CreateString("query"));
            cJSON_AddItemToObject(cjson_Websocket_send ,"userAgent" ,cJSON_CreateString("device"));
            cJSON_AddItemToObject(cjson_Websocket_send ,"apikey" ,cJSON_CreateString(user_apikey));
            cJSON_AddItemToObject(cjson_Websocket_send ,"deviceid" ,cJSON_CreateString(deviceID));
            cJSON_AddItemToObject(cjson_Websocket_send, "params", cjson_params);
        }
        /*step4 : update*/
        cjson_send = cJSON_PrintUnformatted(cjson_Websocket_send);
        debugPrint("[%s]update cjson is :\n%s\n",__FUNCTION__,cjson_send);
        len = produceWebsocktData(cjson_send, send_buf);
        ret = writeToServer(p_socket,send_buf,len);
        pFree(cjson_send);
        cJSON_Delete(cjson_params);
        cJSON_Delete(cjson_Websocket_send);
    }

    return 0;
}

int writeDateQueryToServer(void)
{
    uint8_t deviceID[STRING_DEVICE_ID_LEN] = "wrong ID!";
    uint8_t apikey[STRING_API_KEY_LEN] = "wrong apikey!";
    uint8_t rom_version[STRING_ROM_VERSION_LEN] = "wrong FW";

    cJSON *cjson_userAPIKey = NULL;
    cJSON *cjson_Websocket_send = NULL;
    char *cjson_send = NULL;

    int32_t ret,len;
    uint8_t send_buf[500] = {0};
    
    cJSON_Hooks memoryHook;

    memoryHook.malloc_fn = pMalloc;
    memoryHook.free_fn = pFree;
    cJSON_InitHooks(&memoryHook);
    /*step0 : make sure stream is ok*/
    if(communicate_state != LSERVER_REGISTER_IS_READY)
    {
        return -1;
    }

    /*step1 : get device info*/
    ret = getDeviceInfo(deviceID,apikey);
    ret = getFWVersion(rom_version);

    /*step3 : make update data*/
    if( (cjson_Websocket_send = cJSON_CreateObject()) != NULL)
    {
        cJSON_AddItemToObject(cjson_Websocket_send ,"action" ,cJSON_CreateString("date"));
        cJSON_AddItemToObject(cjson_Websocket_send ,"userAgent" ,cJSON_CreateString("device"));
        cJSON_AddItemToObject(cjson_Websocket_send ,"apikey" ,cJSON_CreateString(user_apikey));
        cJSON_AddItemToObject(cjson_Websocket_send ,"deviceid" ,cJSON_CreateString(deviceID));
    }
    /*step4 : update*/
    cjson_send = cJSON_PrintUnformatted(cjson_Websocket_send);
    debugPrint("[%s]update cjson is :\n%s\n",__FUNCTION__,cjson_send);
    len = produceWebsocktData(cjson_send, send_buf);
    ret = writeToServer(p_socket,send_buf,len);
    pFree(cjson_send);
    cJSON_Delete(cjson_Websocket_send);

    return 0;

}

int readFromServerByIotgoType(uint8_t type, uint8_t *sequence, uint8_t *params)
{
    IOTGO_DATA_TYPE buf;
    signed char ret = -1;
    
    if(communicate_state != LSERVER_REGISTER_IS_READY)
    {
        return -1;
    }

    memset(&buf,0,sizeof(IOTGO_DATA_TYPE));

    ret = readFromIotgoDataPool(type,&buf);
    if(ret == 0)
    {
        memcpy(sequence,buf.sequence,13);
        memcpy(params,buf.params,strlen(buf.params));
        return 0;
    }
    return -1;
}


/* support functions*/

static int produceWebsocktData(char *data, char *buf)
{
    int data_len;
    int header_index = 0;
    int len = 0;
    int ret = -1;
    
    data_len = strlen(data);
    
    header_index = 0;
    buf[header_index++] = 0x81; /* Final package and text data type */
    if (data_len >= 0 && data_len <=125)
    {
        buf[header_index++] = 0x80 + data_len;
    }
    else if (data_len >= 126 && data_len <= 65500)
    {
        buf[header_index++] = 0x80 + 126;
        buf[header_index++] = (data_len >> 8) & 0xFF;
        buf[header_index++] = (data_len) & 0xFF;
    }
    else 
    {
        debugPrint("[%s]The length of the data is too large. Discard it.\n",__FUNCTION__);
    }
    
    buf[header_index++] = 0x00;   /* masking key = 0*/
    buf[header_index++] = 0x00;   /* masking key = 0*/
    buf[header_index++] = 0x00;   /* masking key = 0*/
    buf[header_index++] = 0x00;   /* masking key = 0*/
    
    memcpy(&buf[header_index], data, data_len);
    len = data_len + header_index;
    
    return len;
}

static void store_dev_config(cJSON *devConfig)
{
    IOTGO_DATA_TYPE buf;

    cJSON_Hooks memoryHook;

    char *tmp = NULL;

    memoryHook.malloc_fn = pMalloc;
    memoryHook.free_fn = pFree;
    cJSON_InitHooks(&memoryHook);

    memset(&buf,0,sizeof(IOTGO_DATA_TYPE));
    debugPrint("[%s] \"devConfig\" got!!\n",__FUNCTION__);
    tmp = cJSON_PrintUnformatted(devConfig);
    debugPrint("[%s] devConfig is \n%s\n",__FUNCTION__,tmp);
    debugPrint("[%s] devConfig len is %d\n",__FUNCTION__,strlen(tmp));

    memcpy(buf.params,tmp,strlen(tmp));
    pFree(tmp);
    debugPrint("[%s] testpoint\n",__FUNCTION__);
    memcpy(buf.sequence,"devConfig",9);
    buf.type = TYPE_UPDATE;
    writeToIotgoDataPool(&buf);
}

static void parse_iotgo_data(cJSON *root)
{
    uint8_t flag_date = 0;
    uint8_t flag_params = 0;

    IOTGO_DATA_TYPE buf;
    
    cJSON_Hooks memoryHook;

    memoryHook.malloc_fn = pMalloc;
    memoryHook.free_fn = pFree;
    cJSON_InitHooks(&memoryHook);

    cJSON *cjson_error = NULL;
    cJSON *cjson_action = NULL;
    cJSON *cjson_sequence = NULL;
    cJSON *cjson_params = NULL;
    cJSON *cjson_date = NULL;

    char *tmp = NULL;

    /*step1 : init data buf*/
    memset(&buf,0,sizeof(IOTGO_DATA_TYPE));

    /*step2 : find "sequence"*/
    cjson_sequence = cJSON_GetObjectItem(root,"sequence");
    if(cjson_sequence)
    {
        debugPrint("[%s] \"sequence\" got!!\n",__FUNCTION__);
        memcpy(buf.sequence,cjson_sequence->valuestring,13);
    }

    /*step3 : find "params" */
    cjson_params = cJSON_GetObjectItem(root,"params");
    if(cjson_params)
    {
        debugPrint("[%s] \"params\" got!!\n",__FUNCTION__);
        tmp = cJSON_PrintUnformatted(cjson_params);
        debugPrint("[%s] params len is %d\n",__FUNCTION__,strlen(tmp));
        memcpy(buf.params,tmp,strlen(tmp));
        pFree(tmp);
        flag_params = 1;
    }

    /*step4 : find "date" */
    cjson_date = cJSON_GetObjectItem(root,"date");
    if(cjson_date)
    {
        debugPrint("[%s] \"date\" got!!\n",__FUNCTION__);
        memcpy(buf.params,cjson_date->valuestring,strlen(cjson_date->valuestring));
        flag_date = 1;
    }


    /*step5 : find "action", server send command to device*/
    cjson_action = cJSON_GetObjectItem(root,"action");
    if(cjson_action)
    {
        debugPrint("[%s] \"action\" got!!\n",__FUNCTION__);
        /*step4 : find "update" */
        if(strcmp(cjson_action->valuestring,"update") == 0)
        {
            debugPrint("[%s] \"update\" got!!\n",__FUNCTION__);
            /* store the data to applications*/
            buf.type = TYPE_UPDATE;   
        }
        /* query */
        else if(strcmp(cjson_action->valuestring,"query") == 0)
        {
            /*not supported now*/		
            ;
        }
        /* upgrade */
        else if(strcmp(cjson_action->valuestring,"upgrade") == 0)
        {
            debugPrint("[%s] \"upgrade\" got!!\n",__FUNCTION__);
            buf.type = TYPE_UPGRADE;    
        }
        /* redirect */
        else if(strcmp(cjson_action->valuestring,"redirect") == 0)
        {
            /*not supported now*/
            ;
        }
        /* notify */
        else if(strcmp(cjson_action->valuestring,"notify") == 0)
        {
            /*not supported now*/
            ;
        }
        else
        {
            /*not supported now*/
            ;
        }
    }//cjson_action
    
    /*step3 find "error", server response to device*/
    cjson_error = cJSON_GetObjectItem(root,"error");
    if(cjson_error)
    {
        /* find the date that server returns to device*/
        if(flag_date == 1)
        {
            buf.type = TYPE_DATE;
        }
        /* find the data that device queried from server*/
        if(flag_params == 1)
        {
            buf.type = TYPE_PARAM;
        }
    }
    /*store the data*/
    if(buf.type !=  0)
    {
        writeToIotgoDataPool(&buf);
    }
}

static void first_update_to_server(cJSON *cjson_root)
{
    uint8_t deviceID[STRING_DEVICE_ID_LEN] = "wrong ID!";
    uint8_t apikey[STRING_API_KEY_LEN] = "wrong apikey!";
    uint8_t rom_version[STRING_ROM_VERSION_LEN] = "wrong FW";

    cJSON *cjson_Websocket_read = NULL;
    cJSON *cjson_userAPIKey = NULL;
    cJSON *cjson_Websocket_send = NULL;
    cJSON *cjson_params = NULL;
    char *cjson_send = NULL;
    
    uint8_t send_buf[500];
    int32_t ret = -1;
    int32_t len = -1;
    
    cJSON_Hooks memoryHook;

    memoryHook.malloc_fn = pMalloc;
    memoryHook.free_fn = pFree;
    cJSON_InitHooks(&memoryHook);

    /*step1 : get device info*/
    ret = getDeviceInfo(deviceID,apikey);
    ret = getFWVersion(rom_version);

    /*step2 : get user_apikey info*/
    cjson_Websocket_read = cjson_root;
    if(cjson_Websocket_read)
    {
        cjson_userAPIKey = cJSON_GetObjectItem( cjson_Websocket_read, "apikey");
        if( cjson_userAPIKey )
        {
            memcpy(user_apikey, cjson_userAPIKey->valuestring,36);
            user_apikey[36] = '\0';
            //debugPrint("user_apikey is %s\n",user_apikey);
        }
    }
    /*step3 : make first update data*/
    if( (cjson_Websocket_send = cJSON_CreateObject()) != NULL)
    {
        cJSON_AddItemToObject(cjson_Websocket_send ,"action" ,cJSON_CreateString("update"));
        cJSON_AddItemToObject(cjson_Websocket_send ,"userAgent" ,cJSON_CreateString("device"));
        cJSON_AddItemToObject(cjson_Websocket_send ,"apikey" ,cJSON_CreateString(user_apikey));
        cJSON_AddItemToObject(cjson_Websocket_send ,"deviceid" ,cJSON_CreateString(deviceID));
        cJSON_AddItemToObject(cjson_Websocket_send, "params", cjson_params = cJSON_CreateObject());
        cJSON_AddItemToObject(cjson_params, "fwVersion", cJSON_CreateString(rom_version));
    }
    /*step4 : update*/
    cjson_send = cJSON_PrintUnformatted(cjson_Websocket_send);
    debugPrint("[%s]update cjson is :\n%s\n",__FUNCTION__,cjson_send);
    len = produceWebsocktData(cjson_send, send_buf);
    ret = writeToServer(p_socket,send_buf,len);

    if(cjson_send)
    {
	pFree(cjson_send);
    }

    if(cjson_Websocket_send)
    {
	cJSON_Delete(cjson_Websocket_send);
    }
}

static int sendRegisterMessage(void)
{
    uint8_t model[STRING_DEVICE_MODEL_LEN] = "wrong m!";
    uint8_t deviceID[STRING_DEVICE_ID_LEN] = "wrong ID!";
    uint8_t apikey[STRING_API_KEY_LEN] = "wrong apikey!";
    uint8_t rom_version[STRING_ROM_VERSION_LEN] = "wrong FW";

    uint8_t send_buf[320] = {0};
    uint32_t len = 0;
    uint32_t ret = 0;

    cJSON *cjson_Websocket_send = NULL;
    char *cjson_send = NULL;
    
    cJSON_Hooks memoryHook;

    memoryHook.malloc_fn = pMalloc;
    memoryHook.free_fn = pFree;
    cJSON_InitHooks(&memoryHook);

    /*step1 : get device info*/
    ret = getDeviceInfo(deviceID,apikey);
    ret = getDeviceModel(model);
    ret = getFWVersion(rom_version);

    /*step2 : make register data*/
    if( (cjson_Websocket_send = cJSON_CreateObject()) != NULL)
    {
        cJSON_AddItemToObject(cjson_Websocket_send ,"userAgent" ,cJSON_CreateString("device"));
        cJSON_AddItemToObject(cjson_Websocket_send ,"apikey" ,cJSON_CreateString(apikey));
        cJSON_AddItemToObject(cjson_Websocket_send ,"deviceid" ,cJSON_CreateString(deviceID));
        cJSON_AddItemToObject(cjson_Websocket_send ,"action" ,cJSON_CreateString("register"));
        cJSON_AddItemToObject(cjson_Websocket_send ,"version" ,cJSON_CreateNumber(2));
        cJSON_AddItemToObject(cjson_Websocket_send ,"romVersion" ,cJSON_CreateString(rom_version));
        cJSON_AddItemToObject(cjson_Websocket_send ,"model" ,cJSON_CreateString(model));
        cJSON_AddItemToObject(cjson_Websocket_send ,"ts" ,cJSON_CreateNumber(933));
    }
    /*step3 : send register to server*/
    cjson_send = cJSON_PrintUnformatted(cjson_Websocket_send);
    len = produceWebsocktData(cjson_send, send_buf);
    ret = writeToServer(p_socket,send_buf,len);
    debugPrint("[%s] send register ret is %d\n",__FUNCTION__,ret);
    pFree(cjson_send);
    cJSON_Delete(cjson_Websocket_send);
    return ret;
}


static void data_handle(cJSON *cjson_root)
{

    cJSON *cjson_error = NULL;
    cJSON *cjson_config = NULL;
    cJSON *cjson_devConfig = NULL;
    cJSON *cjson_hd = NULL;
    cJSON *cjson_hbInterval = NULL;

    if(communicate_state != LSERVER_REGISTER_IS_READY)
    {
        cjson_error = cJSON_GetObjectItem(cjson_root,"error");
        cjson_config = cJSON_GetObjectItem(cjson_root,"config");

        if(cjson_error &&
           cjson_error->valueint == 0 )
        {
            debugPrint("[%s]register ok\n",__FUNCTION__);
            first_update_to_server(cjson_root);
            debugPrint("[%s]send first update\n",__FUNCTION__);
            communicate_state = LSERVER_REGISTER_IS_READY;
            if(cjson_config)
            {
                cjson_hd = cJSON_GetObjectItem(cjson_config,"hb");
                cjson_hbInterval = cJSON_GetObjectItem(cjson_config,"hbInterval");
                if(cjson_hd &&
                   cjson_hd->valueint == 1)
                {
                    debugPrint("[%s] start heart beat\n",__FUNCTION__);
                    runHeartBeat(p_socket, cjson_hbInterval->valueint);
                }

		cjson_devConfig = cJSON_GetObjectItem(cjson_config,"devConfig");
		if(cjson_devConfig)
		{
		    store_dev_config(cjson_devConfig);
		}
            }
        }
        else
        {
            sendRegisterMessage();
        }
    }
    else
    {
        parse_iotgo_data(cjson_root);
    }
}

static int32_t handleWebSocketData(void)
{
    int payload_len = 0;
    int offset = 0;
    int32_t ret = 0;
    int32_t count = 0;
    uint8_t buf[2048] = {0};

    cJSON *cjson_root = NULL;
    cJSON *cjson_error = NULL;
    int8_t *cjson_print = NULL;

    memset(buf,0,2048);
    ret = readFromServer(p_socket,buf,2048);
    debugPrint("[%s] readFromServer return is %d\n",__FUNCTION__,ret);
    if(ret > 0)
    {

        debugPrint("\n[%s]data from server :[\n",__FUNCTION__);
	for(count = 0; count < ret; count++)
	{
	    if(buf[count] > 31 && buf[count] < 126)
	    {
	    debugPrint("%c",buf[count]);
	    }
	    else
	    {
	    debugPrint(" 0x%x ",buf[count]);
	    }
	}
	debugPrint("\n]\n\n");


        if(buf[0] == 0x8A &&
	   buf[1] == 0x00) //pong message
	{
	    debugPrint("[%s]heart beat!!!\n",__FUNCTION__);
	}
        else if(buf[0] == 0x81) //text message
        {
            //debugPrint("text message\n");
            payload_len = buf[1] & 0x7F;
            if(payload_len < 126)
            {
                offset = 2;
            }
            else if(payload_len == 126)
            {
                offset = 4;
            }
            else
            {
                offset = 10;
            }

            cjson_root = cJSON_Parse(buf+offset);
            if(cjson_root)
            {
                debugPrint("[%s]websocket data checked\n",__FUNCTION__);
                cjson_print = (int8_t *)cJSON_PrintUnformatted(cjson_root);
                debugPrint("[%s] get data(len is %d):\n%s\n",
                            __FUNCTION__,
			    strlen(cjson_print),
			    cjson_print);
                pFree(cjson_print);
                data_handle(cjson_root);
                cJSON_Delete(cjson_root);
            }
        }
	else
	{
            cjson_root = cJSON_Parse(buf);
            if(cjson_root)
            {
                debugPrint("[%s]websocket data checked\n",__FUNCTION__);
                cjson_print = (int8_t *)cJSON_PrintUnformatted(cjson_root);
                debugPrint("[%s] get data(len is %d):\n%s\n",
                            __FUNCTION__,
			    strlen(cjson_print),
			    cjson_print);
                pFree(cjson_print);
                data_handle(cjson_root);
                cJSON_Delete(cjson_root);
            }
	}
    }
    else
    {
        ret = LSERVER_ERROR_COMMUNICATE;
    }
    //debugPrint("after data parse, ret is %d\n",ret);
    return ret;
}


static int8_t updateToWebSocket(void)
{
    uint8_t buf[500] = {"GET /api/ws HTTP/1.1\r\n"
                   "Host: iotgo.iteadstudio.com\r\n"
                   "Connection: upgrade\r\n"
                   "Upgrade: websocket\r\n"
                   "Sec-WebSocket-Key: ITEADTmobiM0x1DabcEsnw==\r\n"
                     "Sec-WebSocket-Version: 13\r\n\r\n"};
    int32_t ret = -1;
    debugPrint("[%s] prepare for the update message.\r\n",__FUNCTION__);

    ret = writeToServer(p_socket,buf,strlen(buf));
    debugPrint("[%s]write ret is %d\n",__FUNCTION__,ret);
    if(ret < 0)
    {
	return -1;
    }
    memset(buf,0,500);
    ret = readFromServer(p_socket,buf,500);
    debugPrint("[%s] readFromServer ret is %d\n",__FUNCTION__,ret);
    if(ret >= 0)
    {
        if( strstr(buf,"HTTP/1.1 101 Switching Protocols") != NULL )
        {
            return UPDATE_TO_WEBSOCKET_DONE;
        }   
    }
    return -1;
}

int getUserApikey(uint8_t *u_apikey)
{
    memcpy(u_apikey,user_apikey,37);
    return 0;
}
